#ifndef GHOSTSKILL_H
#define GHOSTSKILL_H

#include "gs.h"
#include <QObject>
#include <QDebug>

using namespace gs;

namespace gs
{
// superclass for all individual ghost skills
class GhostSkillObject : public QObject
{
    Q_OBJECT
public:
    explicit GhostSkillObject( Ghost * ghost, GameTable * table )
    {
        _ghost       = ghost;
        _table       = table;
        _has_dice    = false;
        _seal_skills = false;
    }
    virtual bool invokable() { return true; }
    GhostSkill SKILL;
public slots:
    virtual void invoke() = 0;
    virtual void exo_action()
    {
        // do something if the ghost object is exocised
        // and after exo_act stage is finished
        // default nothing
    }
signals:
    void invoked();
protected:
    Ghost *    _ghost;         // the owner of the skill
    GameTable* _table;
    bool       _has_dice;
    bool       _seal_skills;
    Player*    _target_player; // only applies for single target
};

// the true ghost skill format to be list
class GhostSkillList : public QObject, public QList<GhostSkillObject*>
{
    Q_OBJECT
public:
    GhostSkillList( GhostSkills );
    GhostSkills SKILLS;
    bool invokable();
public slots:
    void invoke_all();
    void exo_actions();
signals:
    void invoked_all();
};

// create corresponding ghost skill here.
class GhostSkillFactory : public QObject
{
    Q_OBJECT
public:
    static GhostSkillList * createGhostSkillList( GhostSkills, Ghost *, GameTable * );
protected:
    GhostSkillFactory( QObject *parent = 0 );
    static GhostSkillFactory * _this;
};


/*****
 The list of candidate ghost skills
 (all should inherit from GhostSkillObject)

Object naming conversion:
{abbr.}_GSkill
*****/

// below is the trivial skill object

// one more card
// when invoked, a new card will be asked to be flipped

class OMC_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    OMC_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = ONE_MORE_CARD;
    }
    bool invokable();
    void invoke();
};

// seal skill
// when invoked, the current player's skill is sealed.

class SEALS_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    SEALS_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = SEAL_SKILLS;
    }
    void invoke();
    void exo_action();
private:
    GhostBoard * _target_board;
};

// curse dice
// when invoked, the current player's skill is sealed.

class Curse_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    Curse_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = CURSE_DICE;
    }
    void invoke();
    bool invokable();
private:
    GhostBoard * _target_board;
};

// lose Qi
// the current player lose one Qi
class LQ_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    LQ_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = LOSE_QI;
    }
    void invoke();
};

// lose Fabao
// the current player lose all his fabao
class LF_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    LF_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = LOSE_FABAO;
    }
    void invoke();
};

// dice holder
// the number of dices to be used for exocising ghosts
// is minused by one in tao_act stage
class DH_GSkill : public GhostSkillObject
{
    Q_OBJECT
public:
    DH_GSkill( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = DICE_HOLDER;
    }
    void invoke();
    void exo_action();
};

class QI_Reward : public GhostSkillObject
{
    Q_OBJECT
public:
    QI_Reward( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = QI;
    }
    void invoke();
};

class YINYANG_Reward : public GhostSkillObject
{
    Q_OBJECT
public:
    YINYANG_Reward( Ghost * ghost, GameTable * table = 0 )
        :GhostSkillObject( ghost, table )
    {
        SKILL = YINYANG;
    }
    void invoke();
};


}
#endif // GHOSTSKIL_H
